#include <sstream>

#include "PopupLoggerUI.hpp"
#include "PopupUserUpdateMsg.hpp"

using namespace std;
using namespace Popup;
using namespace PopupUtils;

UserUpdateMsg::UserUpdateMsg(const Message *p_message,
                             const string & p_resourcePath)
: AbstractMessage(POPUP_MSG_TYPE_USER_UPDATE),
  resourcePath(p_resourcePath)
{
  AbstractMessage::deserialize(p_message);
}

bool UserUpdateMsg::onSend()
{
  // Add user ID in any case
  bool _rc = payloadAddLong(USERID, getID());

  // Add nickname
  if (_rc) {
    if ((updateMask & POPUP_USER_FIELD_NICKNAME) != 0) {
      _rc = payloadAddString(USERNICKNAME, getNickname());
    }
  }

  // Add avatar
  if (_rc) {
    if ((updateMask & POPUP_USER_FIELD_AVATAR) != 0) {
      bool _avatarOk = AbstractMessage::payloadAddFileContent(
          AVATAR_RAW_DATA, getAvatar());
      if (_avatarOk) {
        AbstractMessage::payloadAddString(
            AVATAR_FILENAME, PopupUtils::basename(getAvatar()));
      }
      // If we failed to add avatar, as it was the only element to update
      // this is really an error!!
      if (!_avatarOk && updateMask == POPUP_USER_FIELD_AVATAR) {
        _rc = false;
      }
    }
  }

  // Add mode
  if (_rc) {
    if ((updateMask & POPUP_USER_FIELD_MODE) != 0) {
      _rc = payloadAddShort(MODE, getMode());
    }
  }
  // Add health
  if (_rc) {
    if ((updateMask & POPUP_USER_FIELD_HEALTH) != 0) {
      _rc = payloadAddBoolean(HEALTH, isAlive());
    }
  }

  return _rc;
}

bool UserUpdateMsg::onReceive()
{
  string _avatarFilename;
  bool _rc = payloadGetLong(USERID, id);
  stringstream _path;

  if (_rc) {
    // Reset update mask
    updateMask = 0x0000;

    if (payloadGetString(USERNICKNAME, nickname)) {
      updateMask |= POPUP_USER_FIELD_NICKNAME;
    }

    if (payloadGetString(AVATAR_FILENAME, _avatarFilename)) {
      _path << resourcePath <<  "/clients_rc/" << id;
      if (PopupUtils::mkdir(_path.str(), 0755)) {
        _path << "/" << _avatarFilename;
        if (payloadDumpFieldToFile(AVATAR_RAW_DATA, _path.str())) {
          avatar = _path.str();
          updateMask |= POPUP_USER_FIELD_AVATAR;
        }
      } else {
        error("OOOopps!! Failed to create dir %s\n", _path.str().c_str());
      }
    }

    unsigned short _mode;
    if (payloadGetShort(MODE, _mode)) {
      mode = (UserMode) _mode;
      updateMask |= POPUP_USER_FIELD_MODE;
    }

    if (payloadGetBoolean(HEALTH, alive)) {
      updateMask |= POPUP_USER_FIELD_HEALTH;
    }
  }

  return _rc;
}

unsigned short UserUpdateMsg::getUpdateMask() const {
  return updateMask;
}

void UserUpdateMsg::dump() const {
  trace("[User %d updated]", getID());
  trace("Update mask = %04X", updateMask);
  if ((updateMask & POPUP_USER_FIELD_NICKNAME) != 0) {
    trace("Nickname = %s", getNickname().c_str());
  }
  if ((updateMask & POPUP_USER_FIELD_AVATAR) != 0) {
    trace("Avatar   = %s", getAvatar().c_str());
  }
  if ((updateMask & POPUP_USER_FIELD_MODE) != 0) {
    trace("Mode     = %d", getMode());
  }
  if ((updateMask & POPUP_USER_FIELD_HEALTH) != 0) {
    trace("isAlive  = %d", isAlive());
  }
}

